package com.jzo2o.orders.manager.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.api.trade.NativePayApi;
import com.jzo2o.api.trade.TradingApi;
import com.jzo2o.api.trade.dto.request.NativePayReqDTO;
import com.jzo2o.api.trade.dto.response.NativePayResDTO;
import com.jzo2o.api.trade.dto.response.TradingResDTO;
import com.jzo2o.api.trade.enums.PayChannelEnum;
import com.jzo2o.api.trade.enums.TradingStateEnum;
import com.jzo2o.common.expcetions.CommonException;
import com.jzo2o.common.model.msg.TradeStatusMsg;
import com.jzo2o.common.utils.BeanUtils;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.orders.base.enums.OrderPayStatusEnum;
import com.jzo2o.orders.base.enums.OrderStatusEnum;
import com.jzo2o.orders.base.mapper.OrdersMapper;
import com.jzo2o.orders.base.model.domain.Orders;
import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO;
import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO;
import com.jzo2o.orders.manager.porperties.TradeProperties;
import com.jzo2o.orders.manager.service.IOrdersCreateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 下单服务类
 *
 * @author snowWhite
 */
@Slf4j
@Service
public class OrdersCreateServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrdersCreateService {
    //    @Resource
//    private CustomerClient customerClient;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private IOrdersCreateService owner;
    @Resource
    private NativePayApi nativePayApi;
    @Resource
    private TradeProperties tradeProperties;
    @Resource
    private TradingApi tradingApi;

    /**
     * 支付完成，查询结果
     *
     * @param id 订单id
     * @return 订单支付详情体
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrdersPayResDTO payResult(Long id) {
        //查询订单
        Orders orders = getById(id);
        if (ObjectUtils.isNull(orders)) {
            throw new CommonException("订单不存在");
        }
        //判断订单状态
        if (OrderPayStatusEnum.NO_PAY.getStatus() == orders.getPayStatus()
                && ObjectUtils.isNull(orders.getTradingOrderNo())) {
            //未支付：远程调用支付服务查询订单接口
            TradingResDTO tradingResDTO = tradingApi.findTradResultByTradingOrderNo(orders.getTradingOrderNo());
            if (ObjectUtils.isNull(tradingResDTO)) {
                throw new CommonException("订单不存在");
            }
            OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(tradingResDTO, OrdersPayResDTO.class);
            if (ObjectUtils.isNotNull(tradingResDTO.getTransactionId())
                    && TradingStateEnum.YJS == tradingResDTO.getTradingState()) {
                TradeStatusMsg tradeStatusMsg = new TradeStatusMsg();
                tradeStatusMsg.setTradingOrderNo(tradingResDTO.getTradingOrderNo());
                tradeStatusMsg.setProductOrderNo(orders.getId());
                tradeStatusMsg.setTransactionId(tradingResDTO.getTransactionId());
                tradeStatusMsg.setTradingChannel(tradingResDTO.getTradingChannel());
                //更新:支付成功
                owner.paySuccess(tradeStatusMsg);
                ordersPayResDTO.setPayStatus(OrderPayStatusEnum.PAY_SUCCESS.getStatus());
            } else {
                ordersPayResDTO.setPayStatus(OrderPayStatusEnum.NO_PAY.getStatus());
            }
            return ordersPayResDTO;
        }
        //支付：返回
        //更新订单
        OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(orders, OrdersPayResDTO.class);
        ordersPayResDTO.setProductOrderNo(orders.getId());
        return ordersPayResDTO;
    }

    /**
     * 支付完成，修改订单状态
     *
     * @param tradeStatusMsg 支付结果
     */
    @Override
    public void paySuccess(TradeStatusMsg tradeStatusMsg) {
        Orders orders = getById(tradeStatusMsg.getProductOrderNo());
        if (ObjectUtils.isNull(orders)) {
            throw new CommonException("订单不存在");
        }
        if (!OrderStatusEnum.NO_PAY.getStatus().equals(orders.getOrdersStatus())) {
            //订单状态不是未支付，表示不需要更新
            return;
        }
        if (OrderPayStatusEnum.NO_PAY.getStatus() != orders.getPayStatus()) {
            //订单状态不是未支付，表示不需要更新
            return;
        }
        if (ObjectUtils.isNull(tradeStatusMsg.getTransactionId())) {
            //订单三方交易号为空，表示非正规途径完成的订单
            throw new CommonException("没有第三方交易单号");
        }
        //更新订单
        boolean flag = this.lambdaUpdate()
                .eq(Orders::getId, tradeStatusMsg.getProductOrderNo())
                .set(Orders::getOrdersStatus, OrderStatusEnum.DISPATCHING.getStatus())
                .set(Orders::getPayStatus, OrderPayStatusEnum.PAY_SUCCESS.getStatus())
                .set(Orders::getPayTime, tradeStatusMsg.getCreated())
                .set(Orders::getTradingOrderNo, tradeStatusMsg.getTradingOrderNo())
                .set(Orders::getTransactionId, tradeStatusMsg.getTransactionId())
                .set(Orders::getTradingChannel, tradeStatusMsg.getTradingChannel())
                .update();
        if (!flag) {
            throw new CommonException("更新订单支付完成失败");
        }

    }

    /**
     * 确认支付
     *
     * @param id              订单id
     * @param ordersPayReqDTO 订单支付请求体
     * @return 订单支付请求体
     */
    @Override
    @Transactional(rollbackFor = Exception.class) //将来要写分布式事务注解
    public OrdersPayResDTO pay(Long id, OrdersPayReqDTO ordersPayReqDTO) {
        //1.判断当前订单是否已经支付
        Orders orders = getById(id);
        if (ObjectUtils.isNull(orders)) {
            throw new CommonException("订单不存在");
        }
        //已支付，返回支付完成信息
        if (OrderPayStatusEnum.PAY_SUCCESS.getStatus() == orders.getPayStatus()
                && ObjectUtils.isNotNull(orders.getPayTime())
                && ObjectUtils.isNotNull(orders.getTradingOrderNo())
                && ObjectUtils.isNotNull(orders.getTransactionId())) {
            OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(orders, OrdersPayResDTO.class);
            ordersPayResDTO.setProductOrderNo(orders.getId());
            ordersPayResDTO.setTradingChannel(orders.getTradingChannel());
            return ordersPayResDTO;
        }
        //未支付，调用支付服务的下单接口
        return generateQrCode(ordersPayReqDTO, orders);
    }

    /**
     * 生成二维码
     *
     * @param ordersPayReqDTO 支付请求体
     * @param orders          订单
     * @return 订单支付详情体
     */
    private OrdersPayResDTO generateQrCode(OrdersPayReqDTO ordersPayReqDTO, Orders orders) {
        NativePayReqDTO nativePayReqDTO = new NativePayReqDTO();
        PayChannelEnum tradingChannel = ordersPayReqDTO.getTradingChannel();
        Long enterpriseId = tradingChannel ==
                PayChannelEnum.ALI_PAY ? tradeProperties.getAliEnterpriseId() : tradeProperties.getWechatEnterpriseId();
        if (!tradingChannel.getValue().equals(orders.getTradingChannel())) {
            //跟原本传过来的不一样
            nativePayReqDTO.setChangeChannel(true);
        }
        nativePayReqDTO.setTradingChannel(tradingChannel);
        nativePayReqDTO.setMemo(orders.getServeItemName());
        nativePayReqDTO.setProductOrderNo(orders.getId());
        nativePayReqDTO.setEnterpriseId(enterpriseId);
        nativePayReqDTO.setProductAppId("jzo2o.orders");
        nativePayReqDTO.setTradingAmount(orders.getTotalAmount());
        NativePayResDTO nativePayResDTO = nativePayApi.createDownLineTrading(nativePayReqDTO);
        //更新
        boolean flag = this.lambdaUpdate().eq(Orders::getId, orders.getId())
                .set(Orders::getTradingOrderNo, nativePayResDTO.getTradingOrderNo())
                .set(Orders::getTradingChannel, nativePayReqDTO.getTradingChannel())
                .update();
        if (!flag) {
            throw new CommonException("更新订单失败");
        }
        OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(nativePayResDTO, OrdersPayResDTO.class);
        ordersPayResDTO.setPayStatus(OrderPayStatusEnum.NO_PAY.getStatus());
        return ordersPayResDTO;
    }
}
